﻿#include <iostream>
using namespace std;

//class A
//{
//public:
//	virtual void fun1() { cout << "Afun1" << endl; }
//	virtual void fun2() { cout << "Afun2" << endl; }
//	virtual void fun3() { cout << "Afun3" << endl; }
//
//
//	int a = 1;
//};
//
//class B : public A
//{
//public:
//	void fun1() { cout << "Bfun1" << endl; } //重写fun1
//	virtual void fun2() { cout << "Bfun2" << endl; } //重写fun2
//	virtual void fun4() { cout << "Bfun4" << endl; } //B自己的虚函数fun4
//	//继承A的虚函数fun3
//
//	int b = 2;
//};
//
//
//typedef void(*ptr)();
//
//void printptr(ptr arr[])
//{
//	for (int i = 0; arr[i]; ++i)
//	{
//		printf("[%d]: %p\n", i, arr[i]);
//	}
//	cout << endl;
//}
//
//int main()
//{
//	A a;
//	B b;
//
//	//通过对比猜猜虚表存在常量区
//	int i = 0; //栈区
//	static int s = 0; //静态变量
//	const char* c = "abcde"; //常量
//	int* p = new int;//堆区
//
//
//	printf("栈区 %p\n", &i);
//	printf("静态区 %p\n", &s);
//	printf("常量 %p\n", c);
//	printf("堆区 %p\n\n", &p);
//	delete p;
//
//	//打印指针
//	//printptr((ptr*)*((int*)&a)); //取对象四字节地址解引用找虚表中的虚函数地址
//	//printptr((ptr*)*((int*)&b));
//
//	printptr(*(ptr**)&a); //适用于64/32 二级指针指向指针数组然后解引用找到虚表位置
//	printptr(*(ptr**)&b);
//
//
//	return 0;
//}



//class Base1 {
//public:
//	virtual void func1() { cout << "Base1::func1" << endl; }
//	virtual void func2() { cout << "Base1::func2" << endl; }
//private:
//	int b1;
//};
//
//class Base2 {
//public:
//	virtual void func1() { cout << "Base2::func1" << endl; }
//	virtual void func2() { cout << "Base2::func2" << endl; }
//private:
//	int b2;
//};
//
//class Derive : public Base2, public Base1 {
//public:
//	virtual void func1() { cout << "Derive::func1" << endl; }
//	virtual void func3() { cout << "Derive::func3" << endl; }
//private:
//	int d1;
//};
//
//typedef void(*ptr)();
//
//void printptr(ptr* arr)
//{
//	for (int i = 0; arr[i]; ++i)
//	{
//		printf("[%d]: %p\n", i, arr[i]);
//	}
//	cout << endl;
//}
//
//int main()
//{
//	Derive d;
//	//printptr(*(ptr**)&d);
//	Base1* ptr1 = &d;
//	Base2* ptr2 = &d;
//
//	//验证是否调用各自虚表中的fun1
//	ptr1->func1();
//	ptr2->func1();
//	//事实证明按继承顺序，第一个被声明继承的会拿到真正的虚表，其中有真正的虚函数以及d对象自己的虚函数，其他的对象都是通过指针偏移找到第一个被声明的对象的虚表然后访问对应的虚函数
//
//
//	return 0;
//}


class A
{
public:
	virtual void func1()
	{}
public:
	int _a;
};

class B : virtual public A
{
public:
	virtual void func1()
	{}

	virtual void func2()
	{}
public:
	int _b;
};

class C : virtual public A
{
public:
	virtual void func1()
	{}

	virtual void func3()
	{}
public:
	int _c;
};

class D : public B, public C
{
public:
	virtual void func1()
	{

	}
public:
	int _d;
};

int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;

	return 0;
}